package com.loe.ktui.custom

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import com.loe.ktui.*

open class UiFlexList<BEAN>(id: String? = null) : UiFlexLayout(id)
{
    var itemUI: UiFrameLayout? = null
    fun itemUI(block: UiFrameLayout.() -> Unit)
    {
        itemUI = UiFrameLayout()
        itemUI?.block()
    }

    var itemConvert: (KtFrameLayout.(i: Int, bean: BEAN) -> Unit)? = null
    fun itemConvert(itemConvert: KtFrameLayout.(i: Int, bean: BEAN) -> Unit)
    {
        this.itemConvert = itemConvert
    }

    var emptyUI: Any? = null

    var datas: List<BEAN>? = null

    open fun initUI(context: Context, view: KtFlexListView<BEAN>)
    {
        super.initUI(context, view)

        view.itemUI = itemUI
        view.itemConvert = itemConvert

        emptyUI?.let {
            view.emptyView = if (it is UiView) it.createView(context) else View.inflate(context, R.layout.kt_list_empty, null)
        }

        datas?.let { view.setNewData(it) }
    }

    /** 创建view */
    override fun createView(context: Context, parent: ViewGroup?): KtFlexListView<BEAN>
    {
        return KtFlexListView<BEAN>(context).also()
        {
            initUI(context, it)
            addToParent(parent, it)
        }
    }
}

fun <BEAN> Any.ui_FlexList(id: String? = null, block: (UiFlexList<BEAN>.() -> Unit)? = null): UiFlexList<BEAN>
{
    val ui = UiFlexList<BEAN>(id)
    block?.let {
        ui.it()
    }
    if (this is UiGroup) addChild(ui)
    return ui
}

/**
 * 线性布局列表
 */
open class KtFlexListView<BEAN> : KtFlexLayout
{
    constructor(context: Context) : super(context)
    {
        initView()
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    {
        initView()
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    {
        initView()
    }

    private fun initView()
    {
    }

    val list = ArrayList<BEAN>()

    var emptyView: View? = null
        set(value)
        {
            field = value
        }

    fun notifyEmpty()
    {
        if(childCount == 0 && emptyView != null)
        {
            addView(emptyView, MATCH_PARENT, WRAP_CONTENT)
        }
    }

    fun setNewData(list: List<BEAN>)
    {
        clear()
        this.list.addAll(list)
        list.forEach()
        {
            itemUI?.createView(context, this)
        }
        notifyDataChanged()
    }

    fun notifyItemChanged(i: Int)
    {
        val itemView = getChildAt(i) as KtFrameLayout
        itemConvert?.invoke(itemView, i, list[i])
    }

    fun notifyDataChanged()
    {
        if (list.size == childCount)
        {
            list.forEachIndexed()
            { i, bean ->
                val itemView = getChildAt(i) as KtFrameLayout
                itemConvert?.invoke(itemView, i, bean)
            }
        } else
        {
            setNewData(ArrayList(list))
        }
        notifyEmpty()
    }

    fun notifyDataChanged(start: Int, end: Int = list.size - 1)
    {
        if (list.size == childCount)
        {
            list.forEachIndexed()
            { i, bean ->
                if (i in start..end)
                {
                    val itemView = getChildAt(i) as KtFrameLayout
                    itemConvert?.invoke(itemView, i, bean)
                }
            }
        } else
        {
            setNewData(ArrayList(list))
        }
    }

    fun add(bean: BEAN)
    {
        if(list.isEmpty())
        {
            removeAllViews()
        }
        list.add(bean)
        if (itemUI != null)
        {
            val itemView = itemUI!!.createView(context, this)
            itemConvert?.invoke(itemView, list.size - 1, bean)
        }
    }

    fun add(i: Int, bean: BEAN)
    {
        if(list.isEmpty())
        {
            removeAllViews()
        }
        list.add(i, bean)
        if (itemUI != null)
        {
            val itemView = itemUI!!.createView(context, this)
            itemConvert?.invoke(itemView, i, bean)
        }
    }

    fun addAll(aList: List<BEAN>)
    {
        if(list.isEmpty())
        {
            removeAllViews()
        }
        aList.forEach()
        { bean ->
            add(bean)
        }
    }

    fun addAll(i: Int = 0, aList: List<BEAN>)
    {
        if(list.isEmpty())
        {
            removeAllViews()
        }
        aList.forEachIndexed()
        { index, bean ->
            add(index + i, bean)
        }
    }

    fun remove(i: Int = list.size - 1)
    {
        removeViewAt(i)
        list.removeAt(i)
        notifyEmpty()
    }

    fun remove(bean: BEAN)
    {
        val i = list.indexOf(bean)
        removeViewAt(i)
        list.removeAt(i)
        notifyEmpty()
    }

    fun clear()
    {
        list.clear()
        removeAllViews()
    }

    var itemUI: UiFrameLayout? = null
    fun itemUI(block: UiFrameLayout.() -> Unit)
    {
        itemUI = UiFrameLayout()
        itemUI?.block()
    }

    var itemConvert: (KtFrameLayout.(i: Int, bean: BEAN) -> Unit)? = null
    fun itemConvert(itemConvert: KtFrameLayout.(i: Int, bean: BEAN) -> Unit)
    {
        this.itemConvert = itemConvert
    }
}